<template>
  <view class="custom-scroll-view">
    <block v-if="init">
      <scroll-view :style="{height:scrollHeightValue}" scroll-y :show-scrollbar="false" :scroll-top='scrollTop'
        @scroll="handleScroll" @scrolltolower="handleScrolltolower" refresher-enabled
        @refresherrefresh="handleRefresherLoad" :refresher-triggered="refresher_triggered" :refresher-threshold="120"
        :refresher-background="refresherBackground">
        <view>
          <slot :data="data"></slot>
        </view>
        <view class="status-container">
          <text class="text" v-if="data.reqStatus=='loading'">加载中</text>
          <view v-else-if="data.reqStatus=='done'">
            <view class="data-empty" v-if="data.dataStatus=='empty'">
              <view class="empty__image">
                <image src="/static/empty.png"></image>
              </view>
              <text class="empty__description">{{emptyText}}</text>
            </view>
            <text class="text" v-else-if="data.dataStatus=='no-more'">已全部加载完成</text>
            <text class="text" v-else-if="data.dataStatus=='load-more'">上滑加载更多</text>
          </view>
        </view>
      </scroll-view>
    </block>
  </view>
</template>

<script>
  export default {
    name: "custom-scroll-view",
    props: {
      scrollHeight: {
        default: "100%",
        type: String | Number
      },
      // 加载数据方法
      loadData: {
        default: () => {},
        type: Function
      },
      // 暂无数据文案
      emptyText: {
        default: "",
        type: String
      },
      refresherBackground: {
        default: "#e8ebed",
        type: String
      },
      initImmediatelyLoad: {
        default: false,
        type: Boolean
      }
    },
    computed: {
      scrollHeightValue() {
        return typeof this.scrollHeight == 'string' ? this.scrollHeight : this.scrollHeight + 'px';
      }
    },
    data() {
      return {
        init: false,
        scrollTop: 0,
        oldScrollTop: 0,
        // 自定义下拉刷新状态
        refresher_triggered: false,
        data: {
          // 数据列表
          data: [],
          // 当前请求的页数
          page: 1,
          // 总页数
          pages: 0,
          // 状态
          status: '',
        }
      };
    },
    created() {
      this.handleInit();
    },
    mounted() {
      console.log("[custom-scroll-view]", 'mounted');
      this.$nextTick(() => {
        this.init = true;
      })
    },
    methods: {
      // 初始化
      handleInit() {
        this.$set(this, 'data', {
          // 数据列表
          data: [],
          // 当前页数
          page: 1,
          // 总页数
          pages: 0,
          // reqStatus：请求状态
          // - 空 默认状态
          // - loading  加载中
          // - done 加载完成
          reqStatus: '',
          // dataStatus：数据状态
          // - no-more  已获取全部数据
          // - load-more  未获取全部数据 默认状态
          // - empty 数据为空
          dataStatus: 'load-more',
        })

      },
      // 滚动回调事件
      handleScroll(e) {
        let scrollTop = e.detail.scrollTop;
        // 将滚动位置与上次滚动位置传递给父组件
        this.$emit("scroll", {
          scrollTop: scrollTop,
          oldScrollTop: this.oldScrollTop
        });
        // 记录上一次的位置
        this.oldScrollTop = scrollTop
      },
      // 返回顶部
      handleScrollToTop() {
        this.scrollTop = this.oldScrollTop;
        this.$nextTick(() => {
          this.scrollTop = 0
        });
      },
      // 下拉刷新 - 数据长度为0下方可下拉刷新首页
      handleRefresher() {
        console.log("[custom-scroll-view]", 'handleRefresher');
        let len = this.data.data.length
        if (this.initImmediatelyLoad || len == 0) {
          this.handleLoadData(true);
        }
      },
      // 强制下拉刷新
      handleRefresherLoad() {
        console.log("[custom-scroll-view]", 'handleRefresherLoad');
        this.handleLoadData(true);
      },
      // 上拉加载
      handleScrolltolower() {
        this.handleLoadData(false);
      },
      // 加载数据 init为true时为下拉 为false时为上拉
      async handleLoadData(init = false) {
        console.log("[custom-scroll-view]", 'load');
        if (this.data.reqStatus == 'loading') {
          return
        }
        if (init) {
          if (this.refresher_triggered) {
            return;
          }
          console.log("[custom-scroll-view]", 'refresher_triggered true');
          // 加载首页 开启自定义下拉刷新 设置页数参数为1
          this.refresher_triggered = true;
          this.data.page = 0;
          this.data.data = [];
        } else {
          // 已获取全部数据或数据为空状态下 禁止加载下一页
          if (this.data.dataStatus != 'load-more') {
            return;
          }
        }
        this.data.reqStatus = 'loading';
        console.log("[custom-scroll-view]", 'load start');
        // 设置状态为加载中
        let {
          success,
          data,
          pages
        } = await this.loadData.call(this.$parent, this.data.page + 1);
        // 因作用域问题 所以使用call改变作用域为父级实例
        if (success) {
          this.data.pages = pages;
          this.data.page++;
        }
        if (init) {
          // 首页加载 数据采用直接赋值方式，并且设置init为true，标识已加载过首页
          this.$set(this.data, 'data', data);
          this.refresher_triggered = false;
        } else {
          // 非首页加载 数据采用追加的方式
          this.data.data.push(...data);
        }
        this.data.reqStatus = 'done';
        let dataStatus = 'done'
        // 当前页数小于总页数 设置状态为done
        if (this.data.page < this.data.pages) {
          dataStatus = 'load-more';
        }
        // 当前页数大于等于总页数 设置状态为no-more
        if (this.data.page >= this.data.pages && this.data.pages != 0) {
          dataStatus = 'no-more';
        }
        // 首页加载时 获取的数据列表内容长度为0 则设置状态为empty
        if (this.data.pages == 0) {
          dataStatus = 'empty';
        }
        this.$set(this.data, 'dataStatus', dataStatus)
        console.log("[custom-scroll-view]", 'load end', {
          success,
          data,
          pages
        });
      }
    }
  }
</script>

<style lang="scss" scoped>
  .custom-scroll-view {
    width: 100%;
    height: 100%;

    scroll-view {
      width: 100%;
      height: 100%;



      .status-container {
        text-align: center;
        padding-bottom: 32rpx;
        padding-top: 32rpx;

        // 列表数据为空时展示容器
        .data-empty {
          box-sizing: border-box;
          padding: 64px 0;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;

          .empty__image {
            width: 320rpx;
            height: 320rpx;

            image {
              width: 100%;
              height: 100%;
            }
          }

          .empty__description {
            margin-top: 32rpx;
            padding: 0 120rpx;
            color: #969799;
            font-size: 28rpx;
            line-height: 40rpx;
          }
        }

        .text {
          font-size: 24rpx;
          color: #ccc
        }
      }
    }
  }
</style>